use anyhow::{anyhow, Result};
use model_graph_types::container::process::{
    CommandProcessOptions, Process, ProcessOptions, ProcessType,
};
use std::io::BufRead;
use std::process::{id, Child, Command, Output, Stdio};
use std::sync::{Arc, Mutex, RwLock};
use tokio::task::{spawn, JoinHandle};

pub async fn start(identifier: &String, options: &CommandProcessOptions) -> anyhow::Result<u32> {
    let pid = crate::process::generate_pid()?;

    let command = options.command.clone();
    let identifier_m = identifier.clone();

    let child = if cfg!(target_os = "windows") {
        Command::new("cmd")
            .arg("/C")
            .arg(command)
            .stdout(Stdio::piped())
            .stderr(Stdio::piped())
            .spawn()
            .map_err(|err| anyhow!("调用命令失败:{}", err))?
    } else {
        Command::new("sh")
            .arg("-c")
            .arg(command)
            .stdout(Stdio::piped())
            .stderr(Stdio::piped())
            .spawn()
            .map_err(|err| anyhow!("调用命令失败:{}", err))?
    };

    let child_arc: Arc<Mutex<Child>> = Arc::new(Mutex::new(child));

    let child_arc_mv = child_arc.clone();

    let handle: JoinHandle<u32> = spawn(async move {
        //
        while true {
            // 进程退出后结束循环
            if let Ok(Some(exit_status_obj)) = child_arc_mv
                .lock()
                .map_err(|err| anyhow!(""))
                .unwrap()
                .try_wait()
            //删除
            {
                let cache_result = crate::process::RUNNING_PROCESSES
                    .write()
                    .map_err(|err| anyhow!("获取锁失败:{}", err));

                match cache_result {
                    Ok(mut cache) => {
                        cache.remove(&identifier_m);
                        tracing::debug!("移除成功!")
                    }
                    Err(_) => {
                        tracing::error!("移除失败!")
                    }
                }
                break;
            } else {
                std::thread::sleep(std::time::Duration::from_secs(1));
            }
        }
        0
    });
    //TODO 判断是否结束

    // let arc_process = Arc::new(Mutex::new());
    let arc_process = (
        Process {
            id: pid,
            r#type: ProcessType::Command,
            identifier: identifier.clone(),
            options: ProcessOptions::Command(options.clone()),
        },
        handle,
        Some(child_arc),
    );

    //添加
    {
        let mut cache = crate::process::RUNNING_PROCESSES
            .write()
            .map_err(|err| anyhow!("{}", err))?;
        cache.insert(identifier.clone(), arc_process);
    }

    Ok(0)
}
